package com.jinzhi.jzweb.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jinzhi.common.base.CoreServiceImpl;
import com.jinzhi.common.utils.StringUtil;
import com.jinzhi.jzweb.dao.TrackDrawDao;
import com.jinzhi.jzweb.domain.StuSignUpComDO;
import com.jinzhi.jzweb.domain.TrackDrawDO;
import com.jinzhi.jzweb.domain.moduleConfig.CareStuSignUpComRealityDO;
import com.jinzhi.jzweb.pojo.LldrawlotsVO;
import com.jinzhi.jzweb.pojo.ScdrawlotsVO;
import com.jinzhi.jzweb.pojo.StudentVO;
import com.jinzhi.jzweb.service.TrackDrawYuLinService;
import com.jinzhi.jzweb.service.moduleConfig.CareStuSignUpComRealityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * <pre>
 * 赛道抽签表（存储抽签信息）
 * </pre>
 * <small> 2024-02-28 09:32:18 | lance</small>
 */
@Service
public class TrackDrawYuLinServiceImpl extends CoreServiceImpl<TrackDrawDao, TrackDrawDO> implements TrackDrawYuLinService {


    @Autowired
    private CareStuSignUpComRealityService careStuSignUpComRealityService;


    private static Set<String> generatedValues1 = new HashSet<>();

    private static Set<String> generatedValues2 = new HashSet<>();

    private static final String[] values1 = {"B1C1", "B2C2"};

    private static final String[] values2 = {"B3C3", "B4C4"};


    public static String getRandomValue(int sc){
        if (sc == 1){
            Random random = new Random();
            String value = values1[random.nextInt(values1.length)];
            while (generatedValues1.contains(value)) {
                value = values1[random.nextInt(values1.length)];
            }
            generatedValues1.add(value);
            if (generatedValues1.size() == values1.length) {
                generatedValues1.clear(); // 如果所有值都已经被随机过一次，则清空集合，重新开始
            }
            return value;
        }else {
            Random random = new Random();
            String value = values2[random.nextInt(values2.length)];
            while (generatedValues2.contains(value)) {
                value = values2[random.nextInt(values2.length)];
            }
            generatedValues2.add(value);
            if (generatedValues2.size() == values2.length) {
                generatedValues2.clear(); // 如果所有值都已经被随机过一次，则清空集合，重新开始
            }
            return value;
        }
    }


    /**
     * 理论抽签
     * @return
     */
    @Override
    @Transactional
    public int trackDrawList() {
        List<CareStuSignUpComRealityDO> careStuSignUpComRealityDOS = careStuSignUpComRealityService.selectList(null); //查询所有考生信息
        if (careStuSignUpComRealityDOS!=null){  //表示有选手可以进行抽签
            int size = careStuSignUpComRealityDOS.size();  //获取共有几个选手
            List<Integer> studentRandom = getStudentRandom(1,size);
            for (int i=0;i<size;i++){
                careStuSignUpComRealityDOS.get(i).setLlCqNumber(String.valueOf(studentRandom.get(i)));
            }
        }else {
            return 1; //失败
        }
        careStuSignUpComRealityService.updateBatchById(careStuSignUpComRealityDOS);
        return 0; //成功
    }

    /**
     * 理论抽签--广州 2024年11月1号
     *  抽签规则  17支队伍 34个人 一支队伍中的一名选手从1-17号抽签。另一名选手从18-34号抽签。
     *
     * @return
     */
    @Override
    public Integer trackDrawListGuangZhou() {
        // 查询所有选手信息
        List<CareStuSignUpComRealityDO> careStuSignUpComRealityDOS = careStuSignUpComRealityService.selectList(null); //查询所有考生信息
        if (careStuSignUpComRealityDOS==null){
            return 1;
        }
        Random random = new Random();
        // 1-17号 选手一
        LinkedList<Integer> numList = new LinkedList<>();
        // 18-34号 选手二
        LinkedList<Integer> numList2 = new LinkedList<>();
        // 循环遍历赋值
        for (int i = 1; i <= careStuSignUpComRealityDOS.size(); i++) {
            if (i<=careStuSignUpComRealityDOS.size()/2){
                numList.add(Integer.valueOf(i));
            }else {
                numList2.add(Integer.valueOf(i));
            }
        }
        // 将固定的序列号去除
        careStuSignUpComRealityDOS.forEach(stuSignUpCom->{
            if (StringUtil.notEmpty(stuSignUpCom.getTrackDraw())){// 固定的有顺序号
                if (Integer.valueOf(stuSignUpCom.getTrackDraw())<=careStuSignUpComRealityDOS.size()/2){
                    numList.remove(Integer.valueOf(stuSignUpCom.getTrackDraw()));
                }else {
                    numList2.remove(Integer.valueOf(stuSignUpCom.getTrackDraw()));
                }
            }
        });
        //打乱一下存放检录号的列表
        Collections.shuffle(numList,random);
        Collections.shuffle(numList2,random);
        // 使用 Map 优化查找效率
        Map<String, List<CareStuSignUpComRealityDO>> unitNameToStudents = careStuSignUpComRealityDOS.stream()
                .collect(Collectors.groupingBy(CareStuSignUpComRealityDO::getUnitName));
        // 循环设置检录序号
        for (List<CareStuSignUpComRealityDO> students : unitNameToStudents.values()) {
            if (students.size() == 2) {
                assignTrackDraw(students.get(0), numList);
                assignTrackDraw(students.get(1), numList2);
            }
        }

        careStuSignUpComRealityService.updateBatchById(careStuSignUpComRealityDOS);

        return 0;
    }

    /**
     * 判断检录序号是否固定，没固定的话就从队列中取一个
     * @param student
     * @param numList
     */
    private void assignTrackDraw(CareStuSignUpComRealityDO student, LinkedList<Integer> numList) {
        if (StringUtil.notEmpty(student.getTrackDraw())) {
            student.setLlCqNumber(student.getTrackDraw());
            numList.remove(Integer.valueOf(student.getTrackDraw()));
        } else {
            student.setLlCqNumber(String.valueOf(numList.getFirst()));
            numList.removeFirst();
        }
    }



    /**
     * 查询上一次抽签接口
     * @return
     */
    @Override
    public Page<LldrawlotsVO> trackList(int current, int number) {
        Page<CareStuSignUpComRealityDO> page = new Page();
        page.setCurrent(current);
        page.setSize(number);
        Page<CareStuSignUpComRealityDO> schoolsPage = careStuSignUpComRealityService.selectPage(page); //查询所有学校信息
        List<CareStuSignUpComRealityDO> schools = schoolsPage.getRecords();
        List<LldrawlotsVO> rst =new ArrayList<>(); //定义最终返回数据。
        String sch = "";
        for (int i=0;i<schools.size();i++){
            if (sch.equals(schools.get(i).getUnitName())){
                continue;
            }
            List<StudentVO> stuSignUpComDOS = careStuSignUpComRealityService.selStudentByunitName(schools.get(i).getUnitName());
            LldrawlotsVO lldrawlotsVO =new LldrawlotsVO();
            lldrawlotsVO.setSchoolName(schools.get(i).getUnitName()); //学校名称
            sch = schools.get(i).getUnitName();
            if (stuSignUpComDOS.size()>0) {
                //学生信息1
                lldrawlotsVO.setStudentName1(stuSignUpComDOS.get(0).getStudentName() != null ? stuSignUpComDOS.get(0).getStudentName() : "");
                lldrawlotsVO.setStudentNumber1(stuSignUpComDOS.get(0).getLlCqNumber() != null ? stuSignUpComDOS.get(0).getLlCqNumber() : "");
            }else {
                lldrawlotsVO.setStudentName1("");
                lldrawlotsVO.setStudentNumber1("");
            }
            if (stuSignUpComDOS.size()>1) {
                //学生信息2
                lldrawlotsVO.setStudentName2(stuSignUpComDOS.get(1).getStudentName() != null ? stuSignUpComDOS.get(1).getStudentName() : "");
                lldrawlotsVO.setStudentNumber2(stuSignUpComDOS.get(1).getLlCqNumber() != null ? stuSignUpComDOS.get(1).getLlCqNumber() : "");
            }else {
                lldrawlotsVO.setStudentName2("");
                lldrawlotsVO.setStudentNumber2("");
            }
            rst.add(lldrawlotsVO);
        }
        Page<LldrawlotsVO> pageRst =new Page<>();
        pageRst.setRecords(rst);
        pageRst.setTotal(schoolsPage.getTotal());
        pageRst.setCurrent(schoolsPage.getCurrent());
        pageRst.setSize(schoolsPage.getSize());
        return pageRst;
    }







    /**
     * 实操抽签
     * @return
     */
    @Override
    @Transactional
    public int sctrackDrawList() {
        List<CareStuSignUpComRealityDO> careStuSignUpComRealityDOS = careStuSignUpComRealityService.selectList(null); //查询所有考生信息
        if (careStuSignUpComRealityDOS!=null){  //表示有选手可以进行抽签
            int size = careStuSignUpComRealityDOS.size();  //获取共有几个选手
            int half1 = size / 2;
            int half2 = size - half1;
            List<Integer> studentRandom = getStudentRandom(1,half1); //前半场序列号
            List<Integer> studentRandom2 = getStudentRandom(1,half2); //后半场序列号
            studentRandom.addAll(studentRandom2);//合并

            //抽取检录号
            for (int i=0;i<size;i++){
                careStuSignUpComRealityDOS.get(i).setScCqNumber(String.valueOf(studentRandom.get(i)));//赛场序号
            }

            //抽取赛道
            Map<String, List<CareStuSignUpComRealityDO>> schoolTrackMap = assignTracks(careStuSignUpComRealityDOS);
            //更新赛道信息
            for (List<CareStuSignUpComRealityDO> trackList : schoolTrackMap.values()) {
                List<String> tracks = new ArrayList<>();
                tracks.add("赛道一");
                tracks.add("赛道二");
                Collections.shuffle(tracks);  // 随机打乱赛道顺序
                for (int i = 0; i < trackList.size(); i++) {
                    trackList.get(i).setScCqTrack(tracks.get(i)); // 赋予选手赛道号
                }
            }

            //抽取场次
            for (List<CareStuSignUpComRealityDO> trackList : schoolTrackMap.values()) {
                for (int i = 0; i < trackList.size(); i++) {
                    trackList.get(i).setScCqSession(i == 0?getRandomValue(1):getRandomValue(2)); // 赋予选手赛道号
                }
            }

        }else {
            return 1; //失败
        }
        careStuSignUpComRealityService.updateBatchById(careStuSignUpComRealityDOS);
        return 0; //成功
    }


    private Map<String, List<CareStuSignUpComRealityDO>> assignTracks(List<CareStuSignUpComRealityDO> applicants) {
        Map<String, List<CareStuSignUpComRealityDO>> schoolTrackMap = new HashMap<>();
        for (CareStuSignUpComRealityDO applicant : applicants) {
            String school = applicant.getUnitName(); // 学校信息
            List<CareStuSignUpComRealityDO> trackList = schoolTrackMap.getOrDefault(school, new ArrayList<>());
            trackList.add(applicant);
            schoolTrackMap.put(school, trackList);
        }
        return schoolTrackMap;
    }


    /**
     * 实操查询上一次抽签接口
     * @return
     */
    @Override
    public Page<ScdrawlotsVO> sctrackList(int current, int number) {
        Page<CareStuSignUpComRealityDO> page = new Page();
        page.setCurrent(current);
        page.setSize(number);
        Page<CareStuSignUpComRealityDO> schoolsPage = careStuSignUpComRealityService.selectPage(page); //查询所有学校信息
        List<CareStuSignUpComRealityDO> schools = schoolsPage.getRecords();
        List<ScdrawlotsVO> rst =new ArrayList<>(); //定义最终返回数据。
        String sch = "";
        for (int i=0;i<schools.size();i++){
            if (sch.equals(schools.get(i).getUnitName())){
                continue;
            }
            List<StudentVO> stuSignUpComDOS = careStuSignUpComRealityService.selStudentByunitName(schools.get(i).getUnitName());
            ScdrawlotsVO scdrawlotsVO =new ScdrawlotsVO();
            scdrawlotsVO.setSchoolName(schools.get(i).getUnitName()); //学校名称
            sch = schools.get(i).getUnitName();
            if (stuSignUpComDOS.size()>0) {
                //学生信息1
                scdrawlotsVO.setStudentName1(stuSignUpComDOS.get(0).getStudentName() != null ? stuSignUpComDOS.get(0).getStudentName() : ""); //考生名字
                scdrawlotsVO.setStudentNumber1(stuSignUpComDOS.get(0).getScCqNumber() != null ? stuSignUpComDOS.get(0).getScCqNumber() : ""); //检录序号
                scdrawlotsVO.setStudentTrack1(stuSignUpComDOS.get(0).getScCqTrack() !=null ? stuSignUpComDOS.get(0).getScCqTrack() : ""); //赛道
                scdrawlotsVO.setStudentSession1(stuSignUpComDOS.get(0).getScCqSession() !=null ? stuSignUpComDOS.get(0).getScCqSession() : ""); //场次
            }else {
                scdrawlotsVO.setStudentName1(""); //考生名字
                scdrawlotsVO.setStudentNumber1(""); //检录序号
                scdrawlotsVO.setStudentTrack1(""); //赛道
                scdrawlotsVO.setStudentSession1(""); //场次
            }
            if (stuSignUpComDOS.size()>1) {
                //学生信息2
                scdrawlotsVO.setStudentName2(stuSignUpComDOS.get(1).getStudentName() != null ? stuSignUpComDOS.get(1).getStudentName() : ""); //考生名字
                scdrawlotsVO.setStudentNumber2(stuSignUpComDOS.get(1).getScCqNumber() != null ? stuSignUpComDOS.get(1).getScCqNumber() : ""); //检录序号
                scdrawlotsVO.setStudentTrack2(stuSignUpComDOS.get(1).getScCqTrack() !=null ? stuSignUpComDOS.get(1).getScCqTrack() : ""); //赛道
                scdrawlotsVO.setStudentSession2(stuSignUpComDOS.get(1).getScCqSession() !=null ? stuSignUpComDOS.get(1).getScCqSession() : ""); //场次
            }else {
                scdrawlotsVO.setStudentName2(""); //考生名字
                scdrawlotsVO.setStudentNumber2(""); //检录序号
                scdrawlotsVO.setStudentTrack2(""); //赛道
                scdrawlotsVO.setStudentSession2(""); //场次
            }
            rst.add(scdrawlotsVO);
        }
        Page<ScdrawlotsVO> pageRst =new Page<>();
        pageRst.setRecords(rst);
        pageRst.setTotal(schoolsPage.getTotal());
        pageRst.setCurrent(schoolsPage.getCurrent());
        pageRst.setSize(schoolsPage.getSize());
        return pageRst;
    }



    /**
     *
     * @param a 从多少开始
     * @param s 到多少结束
     * @param 假如90个学生就是 a=1  s=90 生成90个随机数的集合包含1和90
     * @return
     */
    private static List<Integer> getStudentRandom(int a,int s){
        System.out.println("++++++++"+a+"+++++++++"+s);
        List<Integer> numbers = new ArrayList<>();
        for (int i = a; i <= s; i++) {
            numbers.add(i);
        }

        // 使用 Fisher-Yates 洗牌算法对集合进行随机排序
        Random rand = new Random();
        for (int i = numbers.size() - 1; i > 0; i--) {
            int index = rand.nextInt(i + 1);
            int temp = numbers.get(index);
            numbers.set(index, numbers.get(i));
            numbers.set(i, temp);
        }
        return numbers;
    }

}


